package com.xuelang.component;

import com.xuelang.pipeline.artifact.client.common.exception.BizException;
import com.xuelang.pipeline.artifact.client.common.result.ApiResult;
import com.xuelang.sys.app.sys.exception.UserMd5AuthFailedException;
import dm.jdbc.driver.DMException;
import feign.RetryableException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import jakarta.validation.ConstraintViolationException;
import java.net.SocketTimeoutException;
import java.util.List;

/**
 * 全局异常处理器
 *
 * @author xiwen.zxg
 * @since 2024/5/16
 */
@Slf4j
@ControllerAdvice
@ResponseBody
@Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalExceptionProcessor {

    /**
     * 参数验证 异常处理
     *
     * @param ex ConstraintViolationException
     * @return
     */
    @ResponseBody
    @ExceptionHandler( {Exception.class})
    public ResponseEntity<ApiResult<Object>> handle(Exception ex) {
        ApiResult<Object> result = ApiResult.builder().build();
        if (ex instanceof HttpMessageNotReadableException) {
            result.setMessage("请求参数格式错误");
        } else if (ex instanceof HttpRequestMethodNotSupportedException) {
            result.setMessage("不支持当前请求方法");
        } else if (ex instanceof HttpMediaTypeNotSupportedException) {
            result.setMessage("不支持当前媒体类型");
        } else if (ex instanceof MethodArgumentNotValidException) {
            List<FieldError> fieldErrorList =((MethodArgumentNotValidException) ex).getBindingResult().getFieldErrors();
            for(FieldError fieldError : fieldErrorList){
                log.error(fieldError.getDefaultMessage());
            }
            if(!fieldErrorList.isEmpty()) {
                result.setMessage(fieldErrorList.get(0).getDefaultMessage());
            } else {
                result.setMessage(ex.getMessage());
            };
        } else if (ex instanceof ConstraintViolationException) {
            String message = ((ConstraintViolationException) ex).getConstraintViolations().iterator().next().getMessage();
            result.setMessage(message);
        } else if (ex instanceof BindException){
            List<FieldError> fieldErrorList =((BindException) ex).getFieldErrors();
            for(FieldError fieldError : fieldErrorList){
                log.error(fieldError.getDefaultMessage());
            }
            result.setMessage(ex.getMessage());
        } else if (ex instanceof BizException){
            result.setMessage(ex.getMessage());
        } else if (ex instanceof RetryableException) {
            result.setMessage(ex.getMessage());
        } else if (ex instanceof SocketTimeoutException) {
            result.setMessage(ex.getMessage());
        } else if (ex instanceof DMException) {
            result.setMessage("数据库操作异常,请查看服务日志.");
        } else if (ex instanceof DataIntegrityViolationException) {
            result.setMessage(ex.getMessage());
        } else if (ex instanceof UserMd5AuthFailedException) {
            return new ResponseEntity<>(HttpStatus.FORBIDDEN);
        } else {
            result.setMessage(HttpStatus.INTERNAL_SERVER_ERROR.getReasonPhrase());
            ex.printStackTrace();
        }
        log.error("系统异常>>>{}", ex.getMessage());
        return ResponseEntity.ok(result);
    }

}
